use axum::{async_trait, extract::FromRequestParts, http::{header, StatusCode,request::Parts}};

use crate::{config::app::App, errors::AdminOpError};

// use crate::config::app::App;


#[derive(Debug)]
pub struct AuthOpChecker {
    pub token: String,
}

#[async_trait]
impl <T>FromRequestParts<T> for AuthOpChecker where T:Send+Sync {
    #[doc = r#" If the extractor fails it'll use this "rejection" type. A rejection is"#]
    #[doc = r" a kind of error that can be converted into a response."]
    type Rejection = (StatusCode, String);

    #[doc = r#" check auth header AUTHORIZATION compare simple token in app config"#]
    async fn from_request_parts(parts:&mut Parts,_state :&T) ->  Result<Self,Self::Rejection>{
        
        if let Some(auth_header) = parts.headers.get(header::AUTHORIZATION){
            if let Ok(token) = auth_header.to_str() {
                return Ok(AuthOpChecker{token:token.to_string()});
            }
        }
        Err((StatusCode::UNAUTHORIZED,"".to_string()))
    }
}

impl AuthOpChecker {
    pub fn check(&self,app : &App)->Result<(),AdminOpError> {
        if let Some(secret) = &app.admin_op_secret.clone() {
            if &self.token == secret {
                return Ok(())
            }
        }
        Err(AdminOpError::AuthNotAllowed(format!("{}",&self.token)))
    }
}